﻿using System;
using System.Collections.Generic;
using Citas.Dominio;
using Citas.Persistencia;


namespace Citas.Negocio
{
    public class AdministracionServiceImpl : IAdministracionService
    {
        #region Dependencias
        IAtencionMedicaDAO atencionDAO = null;
        ICitaDAO citaDAO = null;
        IEspecialidadDAO especialidadDAO = null;
        IMedicoDAO medicoDAO = null;
        IMedicoEspecialidadDAO medicoEspecialidadDAO = null;
        IPacienteDAO pacienteDAO = null;
        IRecetaDAO recetaDAO = null;
        IUsuarioDAO usuarioDAO = null;
        #endregion

        //Especialidad____________________________________________________________
        #region Operaciones de negocio Especialidad
        public Especialidad RegistrarEspecialidad(String descripcion)
        {
            //Excepción si falta algún dato requerido
            if (descripcion == null)
                throw new DatosInsuficientesException("Faltan datos para crear la Especialidad");
            //Creación del Poder
            Especialidad especialidadACrear = new Especialidad();
            especialidadACrear.Descripcion = descripcion;
            return especialidadDAO.Crear(especialidadACrear);
        }

        #endregion

        #region Métodos de soporte para entidad Especialidad
        public Especialidad CrearEspecialidad(Especialidad especialidadACrear)
        {
            if (especialidadDAO.ListarPorDescripcion(especialidadACrear.Descripcion) != null)
                throw new EntidadRepetidaException("El Poder ya existe");
            return especialidadDAO.Crear(especialidadACrear);
        }

        public Especialidad ObtenerEspecialidad(Int32 codigo)
        {
            return especialidadDAO.Obtener(codigo);
        }

        public void EliminarEspecialidad(Int32 codigo)
        {
            Especialidad especialidadAEliminar = new Especialidad();
            especialidadAEliminar = especialidadDAO.Obtener(codigo);

            //Excepción si ya está asignado a un médico
            if (medicoEspecialidadDAO.Obtener(codigo) != null)
                throw new EntidadRelacionadaException("La especialidad ya ha sido asignada a un médico!!!");

            especialidadDAO.Eliminar(especialidadAEliminar);
        }

        public Especialidad ModificarEspecialidad(Especialidad especialidadAModificar)
        {
            return especialidadDAO.Modificar(especialidadAModificar);
        }

        public ICollection<Especialidad> ListarEspecialidades()
        {
            return especialidadDAO.ListarTodos();
        }

        public ICollection<Especialidad> ListarEspecialidadPorDescripcion(string descripcion)
        {
            return especialidadDAO.ListarPorDescripcion(descripcion);
        }
        #endregion

        //Medico___________________________________________________________
        #region Operaciones de negocio medico
        public Medico RegistrarMedico(String nombre)
        {
            // Excepción si falta algún dato requerido
            if (nombre == null)
                throw new DatosInsuficientesException("Faltan datos para crear médico");
            // Excepción si ya se registrón el mismo cliente (por su RUC)
            if (medicoDAO.ObtenerPorNombre(nombre) != null)
                throw new EntidadRepetidaException("El médico ya existe");
            // Creación del cliente
            Medico medicoACrear = new Medico();
            medicoACrear.Nombre = nombre;
            return medicoDAO.Crear(medicoACrear);
        }
        #endregion

        #region Métodos de soporte para entidad Medico
        public Medico ObtenerMedico(Int32 codigo)
        {
            return medicoDAO.Obtener(codigo);
        }

        public Medico ObtenerXNombre(string nombre)
        {
            return medicoDAO.ObtenerPorNombre(nombre);
        }

        public Medico ModificarMedico(Medico medicoAModificar)
        {
            return medicoDAO.Modificar(medicoAModificar);
        }

        public void EliminarMedico(Medico medicoAEliminar)
        {
            medicoDAO.Eliminar(medicoAEliminar);
        }

        public ICollection<Medico> ListarMedicos()
        {
            return medicoDAO.ListarTodos();
        }

        public ICollection<Medico> ListarMedicosXNombre(String nombre)
        {
            return medicoDAO.ListarXNombre(nombre);
        }
        #endregion

        //Usuario___________________________________________________________
        #region Operaciones de negocio usuario
        public Usuario RegistrarUsuario(String usuario, String clave, String nombre, String perfil)
        {
            // Excepción si falta algún dato requerido
            if (usuario == null || clave == null || nombre == null || perfil == null)
                throw new DatosInsuficientesException("Faltan datos para crear usuario");
            // Excepción si ya se registrón el mismo cliente (por su RUC)
            if (usuarioDAO.ObtenerPorUsuario(usuario) != null)
                throw new EntidadRepetidaException("El médico ya existe");
            // Creación del cliente
            Usuario usuarioACrear = new Usuario();
            usuarioACrear.NombreUsuario = usuario;
            usuarioACrear.Clave = clave;
            usuarioACrear.Nombre = nombre;
            usuarioACrear.Perfil = perfil;
            return usuarioDAO.Crear(usuarioACrear);
        }
        #endregion

        #region Métodos de soporte para entidad Medico
        public Usuario ObtenerUsuarioXNombreUsuario(String usuario)
        {
            return usuarioDAO.ObtenerPorUsuario(usuario);
        }

        public Usuario ObtenerUsuario(Int32 codigo)
        {
            return usuarioDAO.Obtener(codigo);
        }

        public Usuario ModificarUsuario(Usuario usuarioAModificar)
        {
            return usuarioDAO.Modificar(usuarioAModificar);
        }

        public void EliminarUsuario(Usuario usuarioAEliminar)
        {
            usuarioDAO.Eliminar(usuarioAEliminar);
        }

        public ICollection<Usuario> ListarUsuarios()
        {
            return usuarioDAO.ListarTodos();
        }

        public ICollection<Usuario> ListarUsuariosXNombre(String nombre)
        {
            return usuarioDAO.ListarXNombre(nombre);
        }
        #endregion

        //Paciente___________________________________________________________
        #region Operaciones de negocio

        // Creación del Paciente
        public Paciente RegistrarPaciente(String tipoDocumento, String numeroDocumento, String apellidoPaterno, String apellidoMaterno, String nombres, String codigoSeguro)
        {
            // Excepción si falta algún dato requerido
            if (tipoDocumento == null || numeroDocumento == null || nombres == null || apellidoPaterno == null || apellidoMaterno == null)
                throw new DatosInsuficientesException("Faltan datos para crear el paciente");


            // Excepción si ya se registró el mismo representante (por su Numero de Documento)
            if (pacienteDAO.ObtenerXDoc(numeroDocumento) != null)
                throw new EntidadRepetidaException("El paciente ya existe");

            Paciente pacienteACrear = new Paciente();
            pacienteACrear.TipoDocumento = tipoDocumento;
            pacienteACrear.NumeroDocumento = numeroDocumento;
            pacienteACrear.Nombres = nombres;
            pacienteACrear.ApellidoPaterno = apellidoPaterno;
            pacienteACrear.ApellidoMaterno = apellidoMaterno;
            pacienteACrear.CodigoSeguro = codigoSeguro;
            return pacienteDAO.Crear(pacienteACrear);
        }

        // Modificación del Paciente
        public Paciente ModificarPaciente(Int32 codigoPaciente, String tipoDocumento, String numeroDocumento, String apellidoPaterno, String apellidoMaterno, String nombres, String codigoSeguro)
        {
            // Excepción si falta algún dato requerido
            if (codigoPaciente <= 0 || tipoDocumento == null || numeroDocumento == null || nombres == null || apellidoPaterno == null || apellidoMaterno == null)
                throw new DatosInsuficientesException("Faltan datos para modificar el Representante");

            Paciente pacienteAModificar = new Paciente();
            pacienteAModificar.Codigo = codigoPaciente;
            pacienteAModificar.TipoDocumento = tipoDocumento;
            pacienteAModificar.NumeroDocumento = numeroDocumento;
            pacienteAModificar.Nombres = nombres;
            pacienteAModificar.ApellidoPaterno = apellidoPaterno;
            pacienteAModificar.ApellidoMaterno = apellidoMaterno;
            pacienteAModificar.CodigoSeguro = codigoSeguro;
            return pacienteDAO.Modificar(pacienteAModificar);
        }

        // Eliminacion del Representante
        public void EliminarPaciente(Int32 codigoPaciente)
        {


            // Excepción si el representante no existe
            if (pacienteDAO.Obtener(codigoPaciente) == null)
                throw new DatosInsuficientesException("El paciente no  existe");

            Paciente pacienteAEliminar = new Paciente();
            pacienteAEliminar.Codigo = codigoPaciente;

            pacienteDAO.Eliminar(pacienteAEliminar);
        }
        #endregion

        #region Métodos de soporte para entidad Paciente
        public Paciente ObtenerPaciente(Int32 CodigoPaciente)
        {
            return pacienteDAO.Obtener(CodigoPaciente);
        }
        public ICollection<Paciente> ListarPaciente()
        {
            return pacienteDAO.ListarTodos();
        }
        public ICollection<Paciente> ListarPacienteXDocumento(String documento)
        {
            return pacienteDAO.ListarXDocumento(documento);
        }

        public ICollection<Paciente> ListarPacienteXNombre(String nombre)
        {
            return pacienteDAO.ListarXNombre(nombre);
        }
        
        public Paciente ObtenerPacienteXDoc(String documento)
        {
            return pacienteDAO.ObtenerXDoc(documento);
        }

        #endregion


        //Cita________________________________________________________
        #region Operaciones de negocio citaDAO
        public Cita RegistrarCita(DateTime fechaHora, Int32 codigoPaciente, Int32 codigoMedicoEspecialidad, String numeroConsultorio,
                                    Double precio, String estado)
        {
            // Excepción si falta algún dato requerido
            if (fechaHora == null || codigoPaciente <= 0 || codigoMedicoEspecialidad <= 0 || precio <= 0 ||
                numeroConsultorio == null || estado == null)
                throw new DatosInsuficientesException("Faltan datos para crear Cita");
            // Excepción si ya se registrón el mismo cliente (por su RUC)
            if (citaDAO.ObtenerPorPacienteFecha(codigoPaciente, fechaHora) != null)
                throw new EntidadRepetidaException("Ya existe una cita para el paciente en la fecha indicada");
            // Creación de la cita
            Cita citaACrear = new Cita();
            citaACrear.FechaHora = fechaHora;
            citaACrear.Paciente = pacienteDAO.Obtener(codigoPaciente);
            citaACrear.MedicoEspecialidad = medicoEspecialidadDAO.Obtener(codigoMedicoEspecialidad);
            citaACrear.NumeroConsultorio = numeroConsultorio;
            citaACrear.Precio = precio;
            citaACrear.Estado = estado;
            return citaDAO.Crear(citaACrear);
        }

        public Cita ModificarCita(Int32 numeroCita, DateTime fechaHora, Int32 codigoPaciente, Int32 codigoMedicoEspecialidad, 
                                    String numeroConsultorio, Double precio, String estado)
        {
            // Excepción si falta algún dato requerido
            if (numeroCita <= 0 || fechaHora == null || codigoPaciente <= 0 || codigoMedicoEspecialidad <= 0 || precio <= 0 ||
                numeroConsultorio == null || estado == null)
                throw new DatosInsuficientesException("Faltan datos para crear Cita");
            
            Cita citaAModificar = new Cita();
            citaAModificar.Numero = numeroCita;
            citaAModificar.FechaHora = fechaHora;
            citaAModificar.Paciente = pacienteDAO.Obtener(codigoPaciente);
            citaAModificar.MedicoEspecialidad = medicoEspecialidadDAO.Obtener(codigoMedicoEspecialidad);
            citaAModificar.NumeroConsultorio = numeroConsultorio;
            citaAModificar.Precio = precio;
            citaAModificar.Estado = estado;
            return citaDAO.Modificar(citaAModificar);
        }

        #endregion


        #region Métodos de soporte para entidad Cita
        public Cita ObtenerCita(Int32 codigo)
        {
            return citaDAO.Obtener(codigo);
        }

        public void EliminarCita(Cita citaAEliminar)
        {
            citaDAO.Eliminar(citaAEliminar);
        }

        public ICollection<Cita> ListarCitas()
        {
            return citaDAO.ListarTodos();
        }

        public ICollection<Cita> ListarCitasXNumero(Int32 numero)
        {
            return citaDAO.ListarXNumero(numero);
        }

        public ICollection<Cita> ListarCitasXPaciente(String paciente)
        {
            return citaDAO.ListarXPaciente(paciente);
        }

        public ICollection<Cita> ListarCitaXNumeroODocumento(Int32 numero, String documento)
        {
            Paciente paciente = pacienteDAO.ObtenerXDoc(documento);
            return citaDAO.ListarXNumeroOPaciente(numero, paciente);
        }
        #endregion


        //MedicoEspecialidad___________________________________________________________
        #region Operaciones de negocio MedicoEspecialidad
        public MedicoEspecialidad AgregarMedicoEspecialidad(Int32 codigoMedico, Int32 codigoEspecialidad)
        {
            // Excepción si falta algún dato requerido
            if (codigoMedico <= 0 || codigoEspecialidad <= 0)
                throw new DatosInsuficientesException("Faltan datos para crear registro de asignación de especialidad a médico");

            // Excepción si ya se registró la misma combinación (por médico y especialidad)
            if (medicoEspecialidadDAO.ObtenerPorMedicoYEspecialidad(codigoMedico, codigoEspecialidad) != null)
            {
                throw new EntidadRepetidaException("Ya existe una asignación de la especialidad al médico indicado");
            }
                        
            // Creación del registro
            MedicoEspecialidad medicoEspecialidadACrear = new MedicoEspecialidad();
            medicoEspecialidadACrear.Medico = medicoDAO.Obtener(codigoMedico);
            medicoEspecialidadACrear.Especialidad = especialidadDAO.Obtener(codigoEspecialidad);
            return medicoEspecialidadDAO.Crear(medicoEspecialidadACrear);
        }
        #endregion

        #region Métodos de soporte para entidad MedicoEspecialidad
        public MedicoEspecialidad ObtenerMedicoEspecialidad(int codigo)
        {
            return medicoEspecialidadDAO.Obtener(codigo);
        }

        public MedicoEspecialidad ObtenerXMedicoYEspecialidad(Int32 codigoMedico, Int32 codigoEspecialidad)
        {
            return medicoEspecialidadDAO.ObtenerPorMedicoYEspecialidad(codigoMedico, codigoEspecialidad);
        }

        public MedicoEspecialidad ModificarMedicoEspecialidad(MedicoEspecialidad medicoEspecialidadAModificar)
        {
            return medicoEspecialidadDAO.Modificar(medicoEspecialidadAModificar);
        }

        public void EliminarMedicoEspecialidad(MedicoEspecialidad medicoEspecialidadAEliminar)
        {
            medicoEspecialidadDAO.Eliminar(medicoEspecialidadAEliminar);
        }

        public ICollection<MedicoEspecialidad> ListarMedicoEspecialidad()
        {
            return medicoEspecialidadDAO.ListarTodos();
        }

        public ICollection<MedicoEspecialidad> ListarMedicosXEspecialidad(Int32 codigoEspecialidad)
        {
            return medicoEspecialidadDAO.ListarXEspecialidad(codigoEspecialidad); 
        }
        #endregion


        //AtencionMedica________________________________________________________
        #region Operaciones de negocio AtencionMedica
        public AtencionMedica RegistrarAtencionMedica(Int32 numeroCita, String diagnostico)
        {
            // Excepción si falta algún dato requerido
            if (diagnostico == null)
                throw new DatosInsuficientesException("Faltan datos para crear la atención médica");
            // Excepción si ya se registrón la misma atención (por cita)
            if (atencionDAO.ObtenerPorCita(numeroCita) != null)
                throw new EntidadRepetidaException("Ya existe una cita para el paciente en la fecha indicada");
            // Creación de la atención
            AtencionMedica atencionACrear = new AtencionMedica();
            atencionACrear.Cita = citaDAO.Obtener(numeroCita);
            atencionACrear.Diagnostico = diagnostico;
            return atencionDAO.Crear(atencionACrear);
        }

        public AtencionMedica ModificarAtencionMedica(Int32 codigoAtencion, Int32 numeroCita, String diagnostico)
        {
            // Excepción si falta algún dato requerido
            if (codigoAtencion <= 0 || numeroCita <= 0 || diagnostico == null)
                throw new DatosInsuficientesException("Faltan datos para modificar Atención");

            AtencionMedica atencionAModificar = new AtencionMedica();
            atencionAModificar.Cita = citaDAO.Obtener(numeroCita);
            atencionAModificar.Diagnostico = diagnostico;
            return atencionDAO.Modificar(atencionAModificar);
        }

        #endregion


        #region Métodos de soporte para entidad AtencionMedica
        public AtencionMedica ObtenerAtencionMedica(Int32 codigo)
        {
            return atencionDAO.Obtener(codigo);
        }

        public void EliminarAtencionMedica(AtencionMedica atencionAEliminar)
        {
            atencionDAO.Eliminar(atencionAEliminar);
        }

        public ICollection<AtencionMedica> ListarAtencionMedica()
        {
            return atencionDAO.ListarTodos();
        }
        #endregion

        //Receta________________________________________________________
        #region Operaciones de negocio Receta
        public Receta RegistrarReceta(Int32 codigoAtencion, String medicamento, String indicaciones)
        {
            // Excepción si falta algún dato requerido
            if (codigoAtencion <= 0 || medicamento == null || indicaciones == null)
                throw new DatosInsuficientesException("Faltan datos para crear la receta");
            // Creación de la receta
            Receta recetaACrear = new Receta();
            recetaACrear.Atencion = atencionDAO.Obtener(codigoAtencion);
            recetaACrear.Medicamento = medicamento;
            recetaACrear.Indicaciones = indicaciones;
            return recetaDAO.Crear(recetaACrear);
        }

        public Receta ModificarReceta(Int32 codigoReceta, Int32 codigoAtencion, String medicamento, String indicaciones)
        {
            // Excepción si falta algún dato requerido
            if (codigoReceta <= 0 || codigoAtencion <= 0 || medicamento == null || indicaciones == null)
                throw new DatosInsuficientesException("Faltan datos para modificar la receta");

            Receta recetaAModificar = new Receta();
            recetaAModificar.Codigo = codigoReceta;
            recetaAModificar.Atencion = atencionDAO.Obtener(codigoAtencion);
            recetaAModificar.Medicamento = medicamento;
            recetaAModificar.Indicaciones = indicaciones;
            return recetaDAO.Modificar(recetaAModificar);
        }
        #endregion


        #region Métodos de soporte para entidad Receta
        public Receta ObtenerReceta(Int32 codigo)
        {
            return recetaDAO.Obtener(codigo);
        }

        public void EliminarReceta(Receta recetaAEliminar)
        {
            recetaDAO.Eliminar(recetaAEliminar);
        }

        public ICollection<Receta> ListarReceta()
        {
            return recetaDAO.ListarTodos();
        }

        public ICollection<Receta> ListarRecetaPorAtencion(Int32 codigoAtencion)
        {
            return recetaDAO.ListarXAtencion(codigoAtencion);
        }
        #endregion
    }
}